﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Collections.Specialized;

namespace KgUtils.Providers
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// AutoUnlock is basically implemented. 
    /// The associated logic may be added to more overriden methods
    /// </remarks>
    /// <see>http://www.codeguru.com/csharp/sample_chapter/print.php/c12747</see>
    public class EnhancedSqlMembershipProvider : SqlMembershipProvider
    {
        private int autoUnlockTimeout = 30;    //Default to 30 minutes
        public int AutoUnlockTimeout
        {
            get { return autoUnlockTimeout; }
        }

        public override void Initialize(string name, NameValueCollection config)
        {
            //add an attribute to manage expiring lockouts
            string unlockTimeOut = config["autoUnlockTimeout"];
            if (!unlockTimeOut.IsNullOrEmpty())
                autoUnlockTimeout = Int32.Parse(unlockTimeOut);

            config.Remove("autoUnlockTimeout");
            base.Initialize(name, config);
        }

        /// <summary>
        /// Automatically unlocks the user if the lock timeout has expired.
        /// </summary>
        /// <param name="username">The username of the user to unlock</param>
        /// <returns></returns>
        private bool AutoUnlockUser(string username)
        {
            var mu = this.GetUser(username, false);
            if ((mu != null) && (mu.IsLockedOut) && (mu.LastLockoutDate.ToUniversalTime().AddMinutes(autoUnlockTimeout) < DateTime.UtcNow))
                return mu.UnlockUser();
            else
                //not locked out in the first place or still in lockout period
                return false;
        }

        /// <summary>
        /// Overriden ValidateUser to unlock user if in right conditions.
        /// </summary>
        /// <param name="username">The username of the user to validate</param>
        /// <param name="password">The password of the user to validate</param>
        /// <returns></returns>
        public override bool ValidateUser(string username, string password)
        {
            bool retval = base.ValidateUser(username, password);

            //The account may be locked out at this point
            if (retval == false)
            {
                bool successfulUnlock = AutoUnlockUser(username);
                if (successfulUnlock)
                    //re-attempt the login
                    return base.ValidateUser(username, password);
                else
                    return false;
            }
            else
                return retval;    //first login was successful
        }

        /* public static PasswordExpiryState PasswordHasExpired(MembershipUser usrInfo, int passwordExpiry, int warningPeriod)
         {
             int daysSincePwdChange = Convert.ToInt32(DateTime.Now.Subtract(usrInfo.LastPasswordChangedDate).TotalDays);
             if (daysSincePwdChange > passwordExpiry)
                 return PasswordExpiryState.Expired;
             else if (daysSincePwdChange >= passwordExpiry - warningPeriod)
                 return PasswordExpiryState.AboutToExpire;
             else
                 return PasswordExpiryState.Valid;
         }*/
    }

    //public enum PasswordExpiryState { Expired, AboutToExpire, Valid }
}
